#pragma once

#include <iostream>
#include <cstring>
#include <string>
#include <cerrno>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <functional>

#include "Log.hpp"
#include "Common.hpp"
#include "InetAddr.hpp"
#include "ThreadPool.hpp"

static const uint16_t gport=8080;

#define BACKLOG 8

using namespace LogModule;
using namespace ThreadPoolModule;

using handler_t = std::function<std::string(std::string)>;

class TcpServer
{
    using task_t=std::function<void()>;
    struct ThreadData
    {
        int sockfd;
        TcpServer* self;
    };

public:
    TcpServer(handler_t handler,int port=gport) 
        :_handler(handler),_port(port),_isrunning(false)
    {}
   
    void InitServer() 
    {
        //1.创建tcp socket
        _listensockfd=socket(AF_INET,SOCK_STREAM,0); //Tcp socket
        if(_listensockfd<0)
        {
            LOG(LogLevel::FATAL)<<"socket error";
            Die(SOCKET_ERR);
        }
        LOG(LogLevel::INFO)<<"socket create success,sockf is :"<<_listensockfd;

        struct sockaddr_in local;
        memset(&local,0,sizeof(local));
        local.sin_family=AF_INET;
        local.sin_port=htons(_port);
        local.sin_addr.s_addr=INADDR_ANY;

        //2.bind
        int n=::bind(_listensockfd,CONV(&local),sizeof(local));
        if(n<0)
        {
            LOG(LogLevel::FATAL)<<"bind error";
            Die(BIND_ERR);
        }
        LOG(LogLevel::INFO)<<"bind success,sockf is :"<<_listensockfd;

        //3.tcp是面向连接的，就要求tcp随时随地等待被连接
        //tcp需要将socket设置为监听状态
        n=::listen(_listensockfd,BACKLOG);
        if(n<0)
        {
            LOG(LogLevel::FATAL)<<"listen error";
            Die(LISTEN_ERR);
        }
        LOG(LogLevel::INFO)<<"listen success,sockf is :"<<_listensockfd;

        ::signal(SIGCHLD,SIG_IGN); //子进程退出，OS会自动回收资源，不用wait了
    }

    void HandlerRequest(int sockfd)
    {
        char inbuffer[1024];
        while(true)
        {
            // ssize_t n=::read(sockfd,inbuffer,sizeof(inbuffer)-1);
            ssize_t n=::recv(sockfd,inbuffer,sizeof(inbuffer)-1,0);
            if(n>0)
            {
                inbuffer[n]=0;
                // std::string echo_str="server echo#";
                // echo_str+=inbuffer;

                // ::write(sockfd,echo_str.c_str(),echo_str.size());

                std::string cmd_result=_handler(inbuffer);
                ::send(sockfd,cmd_result.c_str(),cmd_result.size(),0);
            }
            else if(n==0)
            {
                //read如果读取返回值是0，表示client退出
                LOG(LogLevel::INFO)<<"client quit:"<<sockfd;
                break; 
            }
            else
            {
                //读取失败
                break;
            }
        }
        ::close(sockfd);
    }

    static void *ThreadEntry(void *args)
    {
        pthread_detach(pthread_self());
        ThreadData* data=(ThreadData*)args;
        data->self->HandlerRequest(data->sockfd);
        return nullptr;
    }


    void Start() 
    {
        _isrunning=true;
        while(_isrunning)
        {
            //不能直接读取资源
            //1.获取新连接
            struct sockaddr_in peer;
            socklen_t peerlen=sizeof(peer);
            LOG(LogLevel::DEBUG)<<"accept ing ...";
            int sockfd=::accept(_listensockfd,CONV(&peer),&peerlen);
            if(sockfd<0)
            {
                LOG(LogLevel::WARNING)<<"accept error:"<<strerror(errno);
                continue;
            }

            //获取新连接成功
            LOG(LogLevel::INFO)<<"accept success,sockfd is :"<<sockfd;
            InetAddr addr(peer);
            LOG(LogLevel::INFO)<<"client info:"<<addr.Addr();

            //v1
            // HandlerRequest(sockfd);

            //v2 多进程版本
            // pid_t id=fork();
            // if(id==0)
            // {
            //     //child
            //     //子进程继承父进程的文件描述符表，两张，父子各一张
            //     //关闭不需要的fd
            //     ::close(_listensockfd);
            //     if(fork()>0) exit(0); //子进程退出
            //     //孙子进程->孤儿进程

            //     HandlerRequest(sockfd);
            //     exit(0);
            // }

            // ::close(sockfd);

            // int rid=::waitpid(id,nullptr,0);
            // if(rid<0)
            // {
            //     LOG(LogLevel::WARNING)<<"waitpid error";
            // }


            //v3多线程版本
            //文件描述符表共享
            // pthread_t tid;
            // ThreadData *data=new ThreadData;
            // data->sockfd=sockfd;
            // data->self=this;
            // pthread_create(&tid,nullptr,ThreadEntry,data);

            //v4 线程池版本 比较适合处理短任务，或者是用户量少的情况
            task_t f=std::bind(&TcpServer::HandlerRequest,this,sockfd);
            ThreadPool<task_t>::getInstance()->Equeue(f);

            // ThreadPool<task_t>::getInstance()->Equeue([this,sockfd](){
            //     this->HandlerRequest(sockfd);
            // });
        }
    }

    void Stop()
    {
        _isrunning=false;
    }

    ~TcpServer() 
    {}

private:
    int _listensockfd;
    uint16_t _port;
    bool _isrunning;

    //处理上层任务的入口
    handler_t _handler;
};

//查询tcp服务进程
//netstat -tnap    -nltp